'''
Created on Nov 29, 2012

@author: peng
'''
import smtplib
import time
import sys, os
import fileinput
import subprocess
from platform import node
from datetime import datetime
from time import mktime
from time import gmtime, strftime

_INTERVAL = 60 * 60 * 2
_RESPONSE_THRESHOLD = 0.6
_RESPONSE_PERCENT_THRESHOLD = 0.1
_BAD_LOG_LIMIT = 20

_key_file = 'dolphinservice-china.pem'
_web_server_list = ['baina@119.254.86.73', 'baina@119.254.86.70'] 
_locale = 'zh'
_log_time_format = "%d/%b/%Y:%H:%M:%S +0000"


def get_epoch_datetime(value = None):
    if not value:
        value = datetime.utcnow()
    try:
        return int(mktime(value.timetuple()))
    except AttributeError:
        return None

from_time_str = strftime("%a, %d %b %Y %H:00:00", 
                         gmtime(int(time.time()) - _INTERVAL + 60 * 60 * 8))
to_time_str = strftime("%a, %d %b %Y %H:00:00", 
                       gmtime(int(time.time()) + 60 * 60 * 8))

def _get_data(key, value, value_style=''):
    return data_template % (key, value_style, value)

_message = """From: DOLPHIN VOICE RESPONSE MONITOR <dolphin.voice.monitor@gmail.com>
To: To Person <prong@bainainfo.com>
MIME-Version: 1.0
Content-type: text/html
Subject: ***dolphin voice (%s) response monitor report***

%s
"""

def send_mail(body, message=_message, locale=_locale):
    fromaddr = 'app.search.crawler@gmail.com'
    toaddrs = ['prong@bainainfo.com']
    
    if node() in ['rongpeng-ubuntu-vm']:
        toaddrs = ['prong@bainainfo.com']
    
    message = message % (locale, body)
    
    # Credentials
    username = 'dolphin.voice.monitor'
    password = 'youpeng!'
    
    # The actual mail send
    server = smtplib.SMTP('smtp.gmail.com:587')
    server.starttls()
    server.login(username,password)
    server.sendmail(fromaddr, toaddrs, message.encode('utf8'))
    server.quit()
    
log_file_list = ['/home/peng/Downloads/nginx.access.log']
not_exist_file_list = [log_file for log_file in log_file_list if not os.path.exists(log_file)]

body = u''
if len(not_exist_file_list) == len(log_file_list):
    send_mail('log file not exist!')
    exit(1)

if len(not_exist_file_list) <> 0:
    body += u'[Warning][log file not exist]%s<br>' % str(not_exist_file_list)

for file in not_exist_file_list:
    log_file_list.remove(file)

logs_list = list(fileinput.input(log_file_list))
logs = [log.split('\t') for log in logs_list if len(log.split('\t')) == 9]

if not logs:
    print 'log file is empty.'
    exit(0)

latest_time = 0

total_response_time = 0

response_count = 0
bad_response_count = 0
bad_log_list = []

from_log_time = ''
to_log_time = ''

max_response_time = -1
min_response_time = 0

failed_count = 0


def _get_response_time(response):
    times = [float(r.strip()) for r in response.split(',')]
    times = sorted(times)
    return times[0]

for log in sorted(logs, key=lambda log:log[7], reverse=True):
    if not log[3].startswith('POST /api/voice'):
        continue
    
    if response_count == 0:
        latest_time = get_epoch_datetime(datetime.strptime(log[2], _log_time_format)) - _INTERVAL
        response_count += 1
        to_log_time = log[7]
        
        if log[4] == '200':
            response_time = _get_response_time(log[5])
            total_response_time += response_time
            
            max_response_time = response_time
            min_response_time = response_time
        continue
    log_time = get_epoch_datetime(datetime.strptime(log[2], _log_time_format))
    
    # filter log
    #if log_time < latest_time:
    #    continue
    
    # response count
    response_count += 1
    
    # response time
    if log[4] == '200':
        response_time = _get_response_time(log[5])
        total_response_time += response_time
        if max_response_time < response_time:
            max_response_time = response_time
        if min_response_time > response_time:
            min_response_time = response_time
        
        # bad response
        if response_time > _RESPONSE_THRESHOLD:
            bad_response_count += 1
            bad_log_list.append(log)
    else:
        bad_response_count += 1
        bad_log_list.append(log)
        failed_count += 1

    from_log_time = log[7]

body += u'<table>%s</table>'

# total response
data_template = u'<tr><td>%s</td><td %s>%s</td></tr>'

# from/to time
data = _get_data(u'Start Time', from_time_str)
data += _get_data(u'End Time', to_time_str)
data += _get_data(u'All Response', response_count)
data += _get_data(u'Failed', failed_count)
data += _get_data(u'Load(/s)', '%s' % format(response_count/(float(to_log_time) - float(from_log_time)), '.4'))
# avg response time
data += _get_data(u'AVG Response Time(s)', format(float(total_response_time) / response_count, '.4'))
# bad response time
avg_response_percent = float(float(bad_response_count-failed_count) / response_count)
if avg_response_percent > _RESPONSE_PERCENT_THRESHOLD:
    data += _get_data(u'Response Time>%ss' % _RESPONSE_THRESHOLD, '[%s][%s]' % (bad_response_count-failed_count, format(avg_response_percent, '.2%')), 'bgcolor="#ff0000"')
else:
    data += _get_data(u'Response Time>%ss' % _RESPONSE_THRESHOLD, '[%s][%s]' % (bad_response_count-failed_count, format(avg_response_percent, '.2%')))
# min response time
data += _get_data(u'MIN Response Time(s)', min_response_time)
# max response time
data += _get_data(u'MAX Response(s)', max_response_time)
body = body % data

# bad log
if len(bad_log_list) > 0:
    body += '<br><b> Bad Response List: </b><br>'
    bad_log_string = u''
    bad_log_count = 0
    for bad_log in bad_log_list:
        bad_log_count += 1
        if bad_log_count <= _BAD_LOG_LIMIT:
            bad_log_string += str(bad_log) + '<br>'
        else:
            bad_log_string += '...' + '<br>'
            break
    body += bad_log_string

send_mail(body)
